#include "nvs_hashmap.h"
#include "esp_log.h"

static const char *TAG = "NVS_HashMap";
static bool nvs_initialized = false;

ESP_EVENT_DEFINE_BASE(HMap_EVENT);
/**
 * 检查键长度是否合法
 */
static bool is_valid_key(const char *key) {
    if (key == NULL) {
        return false;
    }
    if (strlen(key) >= MAX_KEY_LENGTH) {
        ESP_LOGE(TAG, "键长度超过限制: %s", key);
        return false;
    }
    return true;
}

esp_err_t nvs_hashmap_init(void) {
    if (nvs_initialized) {
        return ESP_OK;
    }
    
    // 初始化NVS
    esp_err_t err = nvs_flash_init();
    if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) {
        // NVS分区被截断，需要删除并重新初始化
        ESP_ERROR_CHECK(nvs_flash_erase());
        err = nvs_flash_init();
    }
    if (err != ESP_OK) {
        ESP_LOGE(TAG, "NVS初始化失败: %d", err);
        return err;
    }
    
    nvs_initialized = true;
    ESP_LOGI(TAG, "NVS HashMap初始化成功");
    return ESP_OK;
}

esp_err_t nvs_hashmap_put_int(const char *key, int value) {
    if (!is_valid_key(key)) {
        return ESP_ERR_INVALID_ARG;
    }
    
    // 打开NVS
    nvs_handle_t handle;
    esp_err_t err = nvs_open(NVS_NAMESPACE, NVS_READWRITE, &handle);
    if (err != ESP_OK) {
        ESP_LOGE(TAG, "无法打开NVS命名空间: %d", err);
        return err;
    }
    
    // 写入整数
    err = nvs_set_i32(handle, key, value);
    if (err != ESP_OK) {
        ESP_LOGE(TAG, "写入整数失败: %d", err);
        nvs_close(handle);
        return err;
    }
    
    // 提交更改
    err = nvs_commit(handle);
    if (err != ESP_OK) {
        ESP_LOGE(TAG, "提交更改失败: %d", err);
    }
    
    // 关闭NVS
    nvs_close(handle);
    return err;
}

esp_err_t nvs_hashmap_put_string(const char *key, const char *value) {
    if (!is_valid_key(key)) {
        return ESP_ERR_INVALID_ARG;
    }
    
    if (value == NULL) {
        ESP_LOGE(TAG, "字符串值不能为空");
        return ESP_ERR_INVALID_ARG;
    }
    
    if (strlen(value) >= MAX_STRING_LENGTH) {
        ESP_LOGE(TAG, "字符串长度超过限制");
        return ESP_ERR_INVALID_SIZE;
    }
    
    // 打开NVS
    nvs_handle_t handle;
    esp_err_t err = nvs_open(NVS_NAMESPACE, NVS_READWRITE, &handle);
    if (err != ESP_OK) {
        ESP_LOGE(TAG, "无法打开NVS命名空间: %d", err);
        return err;
    }
    
    // 写入字符串
    err = nvs_set_str(handle, key, value);
    if (err != ESP_OK) {
        ESP_LOGE(TAG, "写入字符串失败: %d", err);
        nvs_close(handle);
        return err;
    }
    
    // 提交更改
    err = nvs_commit(handle);
    if (err != ESP_OK) {
        ESP_LOGE(TAG, "提交更改失败: %d", err);
    }
    
    // 关闭NVS
    nvs_close(handle);
    return err;
}

esp_err_t nvs_hashmap_get_int(const char *key, int *value) {
    if (!is_valid_key(key) || value == NULL) {
        return ESP_ERR_INVALID_ARG;
    }
    
    // 打开NVS
    nvs_handle_t handle;
    esp_err_t err = nvs_open(NVS_NAMESPACE, NVS_READONLY, &handle);
    if (err != ESP_OK) {
        ESP_LOGE(TAG, "无法打开NVS命名空间: %d", err);
        return err;
    }
    
    // 读取整数
    err = nvs_get_i32(handle, key, (int32_t *)value);
    if (err != ESP_OK) {
        if (err == ESP_ERR_NVS_NOT_FOUND) {
            ESP_LOGD(TAG, "键未找到: %s", key);
        } else {
            ESP_LOGE(TAG, "读取整数失败: %d", err);
        }
    }
    
    // 关闭NVS
    nvs_close(handle);
    return err;
}

esp_err_t nvs_hashmap_get_string(const char *key, char *value, size_t max_length) {
    if (!is_valid_key(key) || value == NULL || max_length == 0) {
        return ESP_ERR_INVALID_ARG;
    }
    
    // 打开NVS
    nvs_handle_t handle;
    esp_err_t err = nvs_open(NVS_NAMESPACE, NVS_READONLY, &handle);
    if (err != ESP_OK) {
        ESP_LOGE(TAG, "无法打开NVS命名空间: %d", err);
        return err;
    }
    
    // 获取字符串长度
    size_t required_size = 0;
    err = nvs_get_str(handle, key, NULL, &required_size);
    if (err != ESP_OK) {
        if (err == ESP_ERR_NVS_NOT_FOUND) {
            ESP_LOGD(TAG, "键未找到: %s", key);
        } else {
            ESP_LOGE(TAG, "获取字符串长度失败: %d", err);
        }
        nvs_close(handle);
        return err;
    }
    
    // 检查缓冲区大小
    if (required_size > max_length) {
        ESP_LOGE(TAG, "缓冲区太小，需要 %d 字节，提供 %d 字节", required_size, max_length);
        nvs_close(handle);
        return ESP_ERR_INVALID_SIZE;
    }
    
    // 读取字符串
    err = nvs_get_str(handle, key, value, &required_size);
    if (err != ESP_OK) {
        ESP_LOGE(TAG, "读取字符串失败: %d", err);
    }
    
    // 关闭NVS
    nvs_close(handle);
    return err;
}

esp_err_t nvs_hashmap_delete(const char *key) {
    if (!is_valid_key(key)) {
        return ESP_ERR_INVALID_ARG;
    }
    
    // 打开NVS
    nvs_handle_t handle;
    esp_err_t err = nvs_open(NVS_NAMESPACE, NVS_READWRITE, &handle);
    if (err != ESP_OK) {
        ESP_LOGE(TAG, "无法打开NVS命名空间: %d", err);
        return err;
    }
    
    // 删除键值对
    err = nvs_erase_key(handle, key);
    if (err != ESP_OK) {
        if (err == ESP_ERR_NVS_NOT_FOUND) {
            ESP_LOGD(TAG, "键未找到: %s", key);
        } else {
            ESP_LOGE(TAG, "删除键值对失败: %d", err);
        }
    } else {
        // 提交更改
        err = nvs_commit(handle);
        if (err != ESP_OK) {
            ESP_LOGE(TAG, "提交更改失败: %d", err);
        }
    }
    
    // 关闭NVS
    nvs_close(handle);
    return err;
}

esp_err_t nvs_hashmap_clear(void) {
    // 打开NVS
    nvs_handle_t handle;
    esp_err_t err = nvs_open(NVS_NAMESPACE, NVS_READWRITE, &handle);
    if (err != ESP_OK) {
        ESP_LOGE(TAG, "无法打开NVS命名空间: %d", err);
        return err;
    }
    
    // 擦除所有键值对
    err = nvs_erase_all(handle);
    if (err != ESP_OK) {
        ESP_LOGE(TAG, "擦除所有键值对失败: %d", err);
    } else {
        // 提交更改
        err = nvs_commit(handle);
        if (err != ESP_OK) {
            ESP_LOGE(TAG, "提交更改失败: %d", err);
        }
    }
    
    // 关闭NVS
    nvs_close(handle);
    return err;
}

esp_err_t nvs_hashmap_key_exists(const char *key, bool *exists) {
    if (!is_valid_key(key) || exists == NULL) {
        return ESP_ERR_INVALID_ARG;
    }
    
    // 打开NVS
    nvs_handle_t handle;
    esp_err_t err = nvs_open(NVS_NAMESPACE, NVS_READONLY, &handle);
    if (err != ESP_OK) {
        ESP_LOGE(TAG, "无法打开NVS命名空间: %d", err);
        return err;
    }
    
    // 尝试获取键的类型
    nvs_type_t type;
    err = nvs_find_key(handle, key, &type);
    if (err == ESP_OK) {
        *exists = true;
    } else if (err == ESP_ERR_NVS_NOT_FOUND) {
        *exists = false;
        err = ESP_OK; // 这是预期的情况，返回成功
    } else {
        ESP_LOGE(TAG, "检查键存在失败: %d", err);
    }
    
    // 关闭NVS
    nvs_close(handle);
    return err;
}  